#pragma once

#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <set>
#include "Log.hpp"
#include "InetAddr.hpp"

class Command
{
    public:
    Command()
    {
        _safe_command.insert("ls");
        _safe_command.insert("which");
        _safe_command.insert("whoami");
        _safe_command.insert("touch");
        _safe_command.insert("pwd");
        _safe_command.insert("ll");

    }
    ~Command(){}
    bool SafeCheck(const std::string &cmdstr)
    {
        for(auto &cmd:_safe_command)
        {
            //只需要比较前缀
            if(strncmp(cmd.c_str(),cmdstr.c_str(),cmd.size())==0)//并不安全，支持组合式的命令：ls;rm -rf
            {
                return true;
            }
        }
        return false;
    }
   std::string  Excute(const std::string &cmdstr)
    {
        if(!SafeCheck(cmdstr))
        {
            return "unsafe";
        }
        std::string result;
        FILE*fp =popen(cmdstr.c_str(),"r");//支持组合式的写法：make clean;make
        if(fp)
        {
            char line[1024];
            while(fgets(line,sizeof(line),fp))
            {
                result +=line;
            }
            return result.empty()?"success":result;
        }
        return "excute error";
    }
    void HandlerCommand(int sockfd,InetAddr addr)
    {
         while (true)
        {
            char commandbuf[1024];//字符串
            ssize_t n = ::recv(sockfd,commandbuf, sizeof(commandbuf) - 1,0);//最后一个参数：阻塞读取
            if (n > 0)
            {
               commandbuf[n]=0;
                LOG(INFO,"get command from client %s ,message : %s\n",addr.AddrStr().c_str(),commandbuf);
                std::string result =Excute(commandbuf);
                ::send(sockfd, result.c_str(), result.size(),0);
            }
            else if (n == 0)
            {
                LOG(INFO, "client %s quiT\n", addr.AddrStr().c_str());
                break;
            }
            else
            {
                LOG(ERROR, "read error :%s\n", addr.AddrStr().c_str());
            }
        }
    }
private:
    std::set<std::string >_safe_command;
};